package com.hibernate.db;

import org.hibernate.Transaction;
import org.hibernate.classic.Session;
import org.junit.Test;

import com.hibernate.domain.Person;
import com.hibernate.utils.HibernateUtils;

public class SessionCacheTest extends HibernateUtils {
	
	/**
	 * 测试session.get()方法是否把对象放入到一级缓存中
	 * 		说明：Session.get()方法把一个对象放入到了一级缓存中
	 */
	@Test
	public void testGet() {
		Session session = sessionFactory.openSession() ;
		Person person = (Person)session.get(Person.class, 2L) ;	//输出查询sql语句
		person = (Person) session.get(Person.class, 2L) ; //没有输出查询sql语句，说明此次获取的person对象是从session缓存中获取的，而不是从数据库中通过sql语句查询得到的
		session.close() ;
	}
	
	/**
	 * session.getStatistics().getEntityCount()
	 * 		查询当前session缓存中实体的个数
	 */
	@Test
	public void testStatistics(){
		Session session = sessionFactory.openSession() ;
		Person person01 = (Person)session.get(Person.class, 1L) ;
		Person person02 = (Person)session.get(Person.class, 2L) ;
		System.out.println("当前session缓存中的实体个数：" + session.getStatistics().getEntityCount());
		session.close() ;
	}
	
	/**
	 * 测试session.save()方法是否把对象放入到一级缓存中
	 * 		说明：session.save()方法把一个对象放入到了一级缓存中
	 */
	@Test
	public void testSave() {
		Session session = sessionFactory.openSession() ;
		Person person = new Person() ;
		person.setName("酷酷") ;
		person.setDescription("哭哭哭") ;
		//把person对象放入到session缓存中；
		session.save(person) ;
		System.out.println("当前session缓存中的实体个数：" + session.getStatistics().getEntityCount());
		Transaction transaction = session.beginTransaction() ;
		//提交事务：将session缓存中对象更新到数据库中的数据表
		transaction.commit() ;
		session.close() ;
	}
	
	/**
	 * 测试session.evict()
	 * 		把一个对象从一级缓存中清除
	 */
	@Test
	public void testEvict() {
		Session session = sessionFactory.openSession() ;
		Person person = (Person) session.get(Person.class, 2L) ;
		System.out.println("当前session缓存中的实体个数:" + session.getStatistics().getEntityCount());
		System.out.println("调用session.evict(person)，清除当前session缓存中的person对象");
		session.evict(person) ;
		System.out.println("当前session缓存中的实体个数:" + session.getStatistics().getEntityCount());
		session.close() ;
 	}
	
	/**
	 * 测试session.clear()
	 * 		把一个对象从一级缓存中清除
	 */
	@Test
	public void testClear() {
		Session session = sessionFactory.openSession() ;
		Person person1 = (Person) session.get(Person.class, 1L) ;
		Person person2 = (Person) session.get(Person.class, 2L) ;
		System.out.println("当前session缓存中的实体个数:" + session.getStatistics().getEntityCount());
		System.out.println("调用session.clear()，清除当前session缓存中的所有对象");
		session.clear() ;
		System.out.println("当前session缓存中的实体个数:" + session.getStatistics().getEntityCount());
		session.close() ;
	}
	
	/**
	 * 测试session.refresh(person)
	 * 		发出sql语句，把数据库的数据同步到session缓存中
	 */
	@Test
	public void testRefresh() {
		Session session = sessionFactory.openSession() ;
		Person person = (Person)session.get(Person.class, 1L) ;
		person.setName("张三002") ;
		System.out.println(person.getName());	//输出"张三002"
		session.refresh(person) ;	//发出sql语句，把数据库的数据同步到session缓存中
		System.out.println(person.getName());	//输出"张三01，与数据库中的数据一致
		session.close() ;
	}
	
	/**
	 * 测试session.flush()
	 * 		把缓存中的数据同步到数据库中
	 * 说明：
	 * 		 当执行session.flush()的时候（前提：事务开启的情况下），hibernate会检查一级缓存中所有的持久化状态的对象，
	 * 		 如果该持久化状态的对象没有标示符的值(ID值)（说明该对象是从临时状态转化过来的），则会发出insert语句，
	 * 		 如果该持久化状态的对象有标示符的值(ID值)（说明该对象是从数据库中提取出来的），则会对照副本，看是否和副本一致
	 * 		 如果一致，则什么都不做，如果不一致，则发出update语句。
	 * 总结：
	 * 		一级缓存提供了一个临时存放对象的一个内存结构，当hibernate对对象进行操作的时候，仅仅改变的是对象的属性，改变的是一级缓存中的对象的属性
	 * 		在session.flush之前的代码可以任意写，因为这个时候，并没有和数据库交互。
	 * 		当执行session.flush的时候，hibernate会检查一级缓存中的对象的情况，发出insert或者update语句。
	 * 		执行完session.flush的时候，不会改变session缓存中的实体信息
	 * 		另外：一级缓存中也包括集合的缓存。
	 */
	@Test
	public void testFlush() {
		Session session = sessionFactory.openSession() ;
		Transaction transaction = session.beginTransaction() ;
		
		Person person01 = new Person() ; //临时状态
		person01.setName("person01") ;
		
		Person person02 = (Person)session.get(Person.class, 2L) ;	//持久化状态
		person02.setName("person02") ;
		
		session.save(person01) ; 	//临时状态->持久化状态
		
		System.out.println(session.getStatistics().getEntityCount());	//查询当前session缓存中实体的个数
		session.flush() ; //把session缓存中的数据同步到数据库中
		System.out.println(session.getStatistics().getEntityCount());	//查询当前session缓存中实体的个数
		transaction.commit() ;
		session.close() ;
	}
	

}
